package com.fzq.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fzq.util.ResponseResult;
import com.fzq.util.ResultCode;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * security认证失败处理器
 *
 * 这个 SimpleAuthenticationFailureHandler 类是 Spring Security 中处理用户认证失败（如登录失败）的处理器，用于在用户登录尝试失败时，返回结构化的 JSON 错误响应。以下是详细解析：
 *
 * 核心作用
 * 替代默认的认证失败行为
 * Spring Security 默认会：
 * 重定向到登录页（表单登录场景）。
 * 返回 HTTP 401 状态码（API 场景）。
 * 通过自定义处理器，可以统一返回业务约定的 JSON 响应。
 * 细化错误类型
 * 根据不同的认证失败原因（如用户名不存在、密码错误），返回不同的业务状态码和提示信息。
 */
@Component
public class SimpleAuthenticationFailureHandler  implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException e) throws IOException, ServletException {

        //返回成功状态码
        ObjectMapper objectMapper=new ObjectMapper();
        ResponseResult<Void> responseResult=null;

        if(e instanceof UsernameNotFoundException) {                        // 用户名不存在，默认改异常被框架隐藏了
            responseResult = ResponseResult.error(ResultCode.USER_ACCOUNT_NOT_EXIST);
        } else if (e instanceof BadCredentialsException) {                  // 用户名或密码错误
            responseResult = ResponseResult.error(ResultCode.USER_CREDENTIALS_ERROR);
        }

        //响应请求转码
        response.setContentType("application/json;charset=UTF-8");
        String json=objectMapper.writeValueAsString(responseResult);
        //输出json字符串到客户端
        PrintWriter printWriter =response.getWriter();
        printWriter.print(json);
        printWriter.flush();
        printWriter.close();
    }
}
